<script lang="ts" setup name="CreateFunStep">
import { ref } from 'vue'
import { _, ikTree } from 'iking-utils'
import useRouteStore from '@g/store/modules/route'
import type { addProParams } from '../interface'
import MenuForm from './../../../system-manage/menu-manage/MenuForm.vue'
import MenuModal from './../../../system-manage/menu-manage/MenuEditModal.vue'
import AddFun from './AddFun.vue'
import DataFunTable from './DataFunTable.vue'
import ShowSql from './ShowSql.vue'
import {
  addFunSave,
  editFunSave,
  getFieldDefault,
  getFieldIgnore,
  getfieldList,
  getSqlPreview
} from '@/MainApp/apis/manage-design'
import { menuApi } from '@/MainApp/apis/menu'

const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: '新建功能'
  },
  editData: {
    type: Object,
    default: () => null
  }
})
const emits = defineEmits<{
  (event: 'cancel'): void
  (event: 'update:visible', value: boolean): void
  (event: 'confirm'): void
}>()
const { msgSuccess, msgError } = useMessage()
const { t } = useConfig()

const dVisible = ref(props.visible)
const active = ref(1)
const activeName = ref('')
const addFunRef = ref()
const dataFunTableRef = ref()
const tabsList = ref<Array<any>>([])
const tableData = ref({})
const primaryField = ref<Array<any>>([])
const showSqlVisible = ref(false)
const previewData = ref<any>(null)
let addFunFormdata: any = {}

let fieldIgnore: any = null
const menuEdit = ref(props.editData?.menu || null)
const menuForm = ref<any>({
  parentId: ''
})
const menuFormRef = ref()
const menuRef = ref()
const menuTree = ref([])
const addMenuVisible = ref(false)
const loading = ref(false)
const routeStore = useRouteStore()
const idList: Array<string> = []
const formMenu = { parentId: '' }
let fieldDefault: any = null

const queryFieldIgnore = async () => {
  const { success, data } = await getFieldIgnore()
  if (success)
    fieldIgnore = data
}
const queryFieldDefault = async () => {
  const { success, data } = await getFieldDefault()
  if (success) {
    fieldDefault = data.map((item: any) => {
      return {
        isDefault: true,
        ...item
      }
    })
  }
}
queryFieldDefault()
queryFieldIgnore()
const handCancel = () => {
  dVisible.value = false
  menuFormRef.value?.resetFields()
  menuRef.value?.menuFormRef?.resetFields()
  addFunRef.value.projectFormRef?.resetFields()
  emits('update:visible', false)
}
const handClosed = () => {
  dVisible.value = false
  menuFormRef.value?.resetFields()
  menuRef.value?.menuFormRef?.resetFields()
  addFunRef.value.projectFormRef?.resetFields()
  emits('cancel')
  handCancel()
}

const validateTable = (data: any) => {
  if (data.domainObjectClassName === '') {
    msgError(`请输入数据映射类名  ::检查${data.tableName}表`)
    return false
  }
  if (data.isPrimary && data.domainTransferObjectClassName === '') {
    msgError(`请输入数据传输类名  ::检查${data.tableName}表`)
    return false
  }
  if (data.fields.length === 0) {
    msgError(`请添加表字段  ::检查${data.tableName}表`)
    return false
  }
  try {
    data.fields.forEach((item: any, index: any) => {
      if (item.tableFieldName === '')
        throw new Error('请填写字段名称')

      const ignore = fieldIgnore.find((ele: any) => ele === item.tableFieldType)
      if (!ignore && item.tableFieldLength === '')
        throw new Error('请填写字段长度')

      if (item.tableFieldType === '')
        throw new Error('请选择字段类型')

      if (item.domainObjectFieldName === '')
        throw new Error('请填写映射字段')

      if (item.domainObjectFieldType === '')
        throw new Error('请选择映射字段类型')

      if (data.isPrimary && item.domainTransferObjectFieldName === '')
        throw new Error('请填写传输字段')

      if (data.isPrimary && item.domainTransferObjectFieldType === '')
        throw new Error('请选择传输字段类型')
      for (let i = index + 1; i < data.fields.length; i++) {
        if (item.tableFieldName === data.fields[i].tableFieldName)
          throw new Error('字段名称不能重复')

        if (item.domainObjectFieldName === data.fields[i].domainObjectFieldName)
          throw new Error('映射字段名称不能重复')

        if (
          data.isPrimary
          && item.domainTransferObjectFieldName
            === data.fields[i].domainTransferObjectFieldName
        )
          throw new Error('传输字段名称不能重复')
      }
      if (data.newTable) {
        const field = fieldDefault.find(
          (ele: any) => ele.tableFieldName === item.tableFieldName
        )

        if (field) {
          throw new Error(
            `新添加表已有默认字段${field.tableFieldName}请勿重复添加`
          )
        }
      }
    })
  }
  catch (e) {
    msgError(`${e}  ::检查${data.tableName}表`)
    return false
  }
  return true
}
const menuValidate = async () => {
  const menu = await menuFormRef.value.validate((valid: any) => {
    if (valid)
      return true
    else return false
  })
  const menuThree = await menuRef.value?.menuFormRef.validate((valid: any) => {
    if (valid)
      return true
    else return false
  })
  if (!menuThree || !menu)
    return false
  return {
    menu: {
      ...menuRef.value.menuForm,
      parentId:
        (menuForm.value.parentId && menuForm.value.parentId.length > 0)
          ? menuForm.value.parentId[menuForm.value.parentId.length - 1]
          : ''
    }
  }
}
const handConfirm = async () => {
  const dataTable = await dataFunTableRef.value.getDataTable()
  if (!dataTable)
    return false
  dataTable.fields = dataTable.fields.map((ele: any) => {
    return {
      ...ele,
      moduleId: props.editData ? props.editData.id : ''
    }
  })
  tabsList.value = tabsList.value.map(item => {
    if (props.editData)
      item.moduleId = props.editData.id

    item.fields = item.fields.map((ele: any) => {
      return {
        ...ele,
        moduleId: props.editData ? props.editData.id : ''
      }
    })
    if (item.tableName === activeName.value)
      return { ...item, ...dataTable }
    return { ...item }
  })
  try {
    tabsList.value.forEach(item => {
      const flag = validateTable(item)
      if (!flag)
        throw new Error('错误')
    })
  }
  catch (e) {
    return
  }
  let params: addProParams = {
    ...addFunFormdata,
    scaffoldType: 'MODULE',
    scaffoldTypeName: '功能',
    moduleTables: tabsList.value
  }
  if (active.value === 3) {
    const menuData = await menuValidate()
    if (!menuData)
      return
    if (menuData) {
      params = {
        ...params,
        ...menuData
      }
    }
  }
  loading.value = true
  if (props.editData)
    params.id = props.editData.id
  const { success, msg } = props.editData
    ? await editFunSave(params)
    : await addFunSave(params)
  if (success) {
    emits('confirm')
    dVisible.value = false
    loading.value = false
    msgSuccess(msg)
    if (active.value === 3)
      routeStore.generateRoutesAtBack()
  }
  else {
    loading.value = false
    msgError(msg)
  }
}
const handPreBtn = async () => {
  if (active.value === 2) {
    const dataTable = await dataFunTableRef.value.getData()
    tabsList.value = tabsList.value.map(item => {
      if (item.tableName === activeName.value)
        return { ...item, ...dataTable }
      return { ...item }
    })
  }
  active.value--
}
const delDuplicates = (arr1: Array<any>, arr2: Array<any>): Array<any> => {
  return Object.values(
    [...arr1, ...arr2].reduce((acc, cur) => {
      acc[cur.tableFieldName] = cur
      return acc
    }, {})
  )
}
const setDefautData = (data: any) => {
  const tableName = data.tableName.split('_')
  let domainObjectClassName = ''
  tableName.forEach((ele: string) => {
    domainObjectClassName += ele.replace(ele[0], ele[0]?.toUpperCase() || '')
  })
  if (data.newTable)
    data.fields = data.fields.length > 0 ? data.fields : []
  if (data.isPrimary) {
    data.domainTransferObjectClassName = `${domainObjectClassName}DTO`
    data.type = 'PRIMARY'
    primaryField.value = _.cloneDeep(data.fields)
    if (data.newTable)
      primaryField.value = delDuplicates(primaryField.value, fieldDefault)
  }
  data.domainObjectClassName = `${domainObjectClassName}DO`
  if (data.tableName === activeName.value) {
    tableData.value = {
      ...data
    }
  }
  return data
}
const queryfieldList = async () => {
  const list: any = []
  tabsList.value.forEach(item => {
    if (!item.newTable)
      list.push(item.tableName)
  })
  if (list.length > 0) {
    const params = {
      datasourceId: addFunFormdata?.datasourceId || '',
      tableNames: list.join(',')
    }
    const { data, success } = await getfieldList(params)
    if (success) {
      tabsList.value.forEach(item => {
        if (!item.newTable) {
          item.fields = []
          const moduleData = props.editData?.moduleTables.find(
            (ele: any) => ele.tableName === item.tableName
          )
          if (moduleData) {
            item.fields = _.cloneDeep(moduleData.fields)
          }
          else {
            data.forEach((e: any) => {
              if (item.tableName === e.tableName)
                item.fields.push(e)
            })
          }
        }
      })
    }
  }
}
const handNextBtn = async () => {
  if (active.value === 1) {
    const data = await addFunRef.value!.addFunConfirm()
    if (data)
      addFunFormdata = { ...data }
    else return
    if (tabsList.value.length > 0) {
      tabsList.value = addFunRef.value!.dataBase.map((item: any) => {
        tabsList.value.forEach((o: any) => {
          if (item.tableName === o.tableName) {
            item = {
              ...item,
              ...o
            }
          }
        })
        return {
          ...item
        }
      })
    }
    else {
      tabsList.value = addFunRef.value!.dataBase || []
    }

    await queryfieldList()
    activeName.value = activeName.value || tabsList.value[0].tableName

    tabsList.value = tabsList.value.map(item => {
      return setDefautData(item)
    })
    if (props.editData) {
      if (
        props.editData.moduleTables
        && props.editData.moduleTables.length > 0
      ) {
        tabsList.value = tabsList.value.map(item => {
          props.editData.moduleTables.forEach((ele: any) => {
            if (item.tableName === ele.tableName) {
              item = {
                ..._.cloneDeep(ele),
                isPrimary: item.isPrimary,
                newTable: item.newTable
              }
            }

            if (item.tableName === activeName.value)
              tableData.value = _.cloneDeep(item)
          })
          if (item.isPrimary) {
            primaryField.value = _.cloneDeep(item.fields)
            if (item.newTable) {
              primaryField.value = delDuplicates(
                primaryField.value,
                fieldDefault
              )
            }
          }

          return { ...item }
        })
      }
    }
  }

  active.value++
}

const beforeLeaveTabs = async (name: any) => {
  const data = dataFunTableRef.value.getData()
  if (data.isPrimary) {
    primaryField.value = _.cloneDeep(data.fields)
    if (data.newTable)
      primaryField.value = delDuplicates(primaryField.value, fieldDefault)
  }
  tabsList.value = tabsList.value.map(item => {
    if (data && item.tableName === data.tableName)
      return { ...data }
    if (item.tableName === name) {
      tableData.value = {
        ...item
      }
    }

    return { ...item }
  })
  activeName.value = name
}
const handSqlBtn = async () => {
  const table = dataFunTableRef.value.getData()
  const { data, success } = await getSqlPreview(table)
  if (success) {
    previewData.value = data
    showSqlVisible.value = true
  }
}
const handleCancel = () => {
  showSqlVisible.value = false
}
const setIdList = (data: any, id: any) => {
  data.forEach((ele: any) => {
    if (ele.id === id) {
      if (ele.parentId && ele.parentId !== '')
        setIdList(data, ele.parentId)

      idList.push(ele.id)
    }
  })
}
const queryMenu = () => {
  menuApi
    .getAllMenu()
    .then(({ success, data, msg }) => {
      if (success) {
        const treeData = data.filter((item: any) => item.menuType !== 'PAGE_BUTTON')
        menuTree.value = ikTree.listToTree(
          treeData.map(
            (item: { key: string; loading: Boolean; }, index: number) => {
              item.key = `${index}`
              item.loading = false
              return item
            }
          )
        )
        if (props.editData && props.editData.menu) {
          setIdList(treeData, props.editData.menu.parentId)
          menuForm.value.parentId = idList
        }
        else {
          menuForm.value = _.cloneDeep(formMenu)
          if (props.editData && props.editData.menuId)
            menuForm.value.id = props.editData.menuId
        }
      }
      else {
        msgError(msg)
      }
    })
    .catch(() => {
      menuTree.value = []
    })
}
queryMenu()
const goMenu = () => {
  addMenuVisible.value = true
}
const onUpdateData = () => {
  queryMenu()
  addMenuVisible.value = false
}
watch(
  () => props.visible,
  async visible => {
    if (visible) {
      active.value = 1
      menuForm.value = _.cloneDeep(formMenu)
      if (props.editData) {
        menuForm.value = props.editData?.menu
          ? { ...props.editData.menu }
          : { parentId: '', id: props.editData.menuId }
        menuEdit.value = props.editData?.menu || null
      }
      await queryMenu()
    }
    else {
      activeName.value = ''
      tabsList.value = []
      tableData.value = {}
    }

    dVisible.value = visible
  }
)
</script>

<template>
  <el-dialog
    v-model="dVisible"
    class="form-design"
    :title="props.editData ? '编辑功能' : '新建功能'"
    width="88%"
    align-center
    :close-on-click-modal="false"
    @closed="handClosed"
  >
    <div class="manage-design">
      <!-- <el-tabs
        v-model="activeName"
        class="demo-tabs"
        @tab-click="handleTabClick"
      >
        <el-tab-pane label="基本信息" name="first">
          <AddFun></AddFun>
        </el-tab-pane>
        <el-tab-pane label="字段配置" name="second">Config</el-tab-pane>
      </el-tabs> -->
      <el-steps :active="active" align-center>
        <el-step title="基本信息" />
        <el-step title="字段配置" />
        <el-step title="菜单配置" />
      </el-steps>
      <AddFun
        v-show="active === 1"
        ref="addFunRef"
        :edit-data="props.editData"
        :visible="props.visible"
      />
      <el-tabs
        v-show="active === 2"
        v-model="activeName"
        class="demo-tabs"
        @tab-change="beforeLeaveTabs"
      >
        <el-tab-pane
          v-for="(item, index) in tabsList"
          :key="index"
          :label="
            item.isPrimary
              ? `${item.tableName}(主表)`
              : `${item.tableName}(从表)`
          "
          :name="item.tableName"
        />
      </el-tabs>
      <DataFunTable
        v-show="active === 2"
        ref="dataFunTableRef"
        :primary-field="primaryField"
        :table-data="tableData"
      />
      <el-row v-show="active === 3">
        <el-col :span="24" class="elcolTitle">
          <p class="projectTitle">菜单信息</p>
        </el-col>
        <el-col :span="24">
          <el-form ref="menuFormRef" :model="menuForm" label-width="140px">
            <el-row>
              <el-col :span="24">
                <el-form-item label="父级菜单" prop="parentId">
                  <el-cascader
                    v-model="menuForm.parentId"
                    clearable
                    placeholder="请选择父级菜单"
                    :options="menuTree"
                    :props="{ label: 'name', value: 'id', checkStrictly: true }"
                  />
                  <el-button
                    class="ml15"
                    type="primary"
                    @click="goMenu"
                  >
                    新建
                  </el-button>
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
        </el-col>
        <MenuForm
          ref="menuRef"
          :visible="props.visible"
          :edit-data="menuEdit"
          :show-auto-render="true"
        />
      </el-row>
      <MenuModal
        v-model:visible="addMenuVisible"
        @update:visible="onUpdateData"
        @updateData="onUpdateData"
      />
      <ShowSql
        :visible="showSqlVisible"
        :preview-data="previewData"
        @confirm="handleCancel"
        @cancel="handleCancel"
      />
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handCancel">{{ t("action.cancel") }}</el-button>
        <el-button
          v-show="active !== 1"
          type="primary"
          @click="handPreBtn"
        >上一步</el-button>
        <el-button v-show="active === 2" type="primary" @click="handSqlBtn">
          预览SQL
        </el-button>
        <el-button
          v-show="active !== 3"
          type="primary"
          @click="handNextBtn"
        >下一步</el-button>
        <el-button
          v-show="active !== 1"
          :loading="loading"
          type="primary"
          @click="handConfirm"
        >
          {{ t("action.sure") }}
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.manage-design {
  padding: 15px;
  background-color: var(--color-background);

  .elcolTitle {
    padding: 15px;
    border-bottom: 1px solid #e5e5e5;
    margin-bottom: 15px;

    .projectTitle {
      font-size: 16px;
      font-weight: 400;
      color: #333;
      padding-left: 10px;
      border-left: 5px solid #409eff;
    }
  }
}
</style>
